home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / uae / uae-0.4.3 / dos-grx.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  13KB  |  528 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * DOS GRX lib svga interface.
  5.   *
  6.   * (c) 1995 Bernd Schmidt
  7.   * (c) 1996 Gustavo Goedert
  8.   */
  9.  
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <stdio.h>
  13. #include <assert.h>
  14. #include <signal.h>
  15. #include <unistd.h>
  16. #include <grx.h>
  17. #include <pc.h>
  18. #include <go32.h>
  19. #include <dpmi.h>
  20.  
  21. #include "config.h"
  22. #include "amiga.h"
  23. #include "options.h"
  24. #include "memory.h"
  25. #include "custom.h"
  26. #include "newcpu.h"
  27. #include "keyboard.h"
  28. #include "xwin.h"
  29. #include "keybuf.h"
  30.  
  31. #define R_WEIGHT 5
  32. #define G_WEIGHT 5
  33. #define B_WEIGHT 5
  34.  
  35. #define SCANCODE_CURSORUP       72
  36. #define SCANCODE_CURSORLEFT     75
  37. #define SCANCODE_CURSORRIGHT    77
  38. #define SCANCODE_CURSORDOWN     80
  39.  
  40. #define SCANCODE_CURSORUPLEFT   71
  41. #define SCANCODE_CURSORUPRIGHT  73
  42. #define SCANCODE_CURSORDOWNLEFT 79
  43. #define SCANCODE_CURSORDOWNRIGHT 81
  44.  
  45. #define SCANCODE_CURSORBLOCKUP  103
  46. #define SCANCODE_CURSORBLOCKLEFT 105
  47. #define SCANCODE_CURSORBLOCKRIGHT 106
  48. #define SCANCODE_CURSORBLOCKDOWN 108
  49.  
  50. #define SCANCODE_KEYPAD0        82
  51. #define SCANCODE_KEYPAD1        79
  52. #define SCANCODE_KEYPAD2        80
  53. #define SCANCODE_KEYPAD3        81
  54. #define SCANCODE_KEYPAD4        75
  55. #define SCANCODE_KEYPAD5        76
  56. #define SCANCODE_KEYPAD6        77
  57. #define SCANCODE_KEYPAD7        71
  58. #define SCANCODE_KEYPAD8        72
  59. #define SCANCODE_KEYPAD9        73
  60. #define SCANCODE_KEYPADENTER    96
  61. #define SCANCODE_KEYPADPLUS     78
  62. #define SCANCODE_KEYPADMINUS    74
  63.  
  64. #define SCANCODE_Q              16
  65. #define SCANCODE_W              17
  66. #define SCANCODE_E              18
  67. #define SCANCODE_R              19
  68. #define SCANCODE_T              20
  69. #define SCANCODE_Y              21
  70. #define SCANCODE_U              22
  71. #define SCANCODE_I              23
  72. #define SCANCODE_O              24
  73. #define SCANCODE_P              25
  74.  
  75. #define SCANCODE_A              30
  76. #define SCANCODE_S              31
  77. #define SCANCODE_D              32
  78. #define SCANCODE_F              33
  79. #define SCANCODE_G              34
  80. #define SCANCODE_H              35
  81. #define SCANCODE_J              36
  82. #define SCANCODE_K              37
  83. #define SCANCODE_L              38
  84.  
  85. #define SCANCODE_Z              44
  86. #define SCANCODE_X              45
  87. #define SCANCODE_C              46
  88. #define SCANCODE_V              47
  89. #define SCANCODE_B              48
  90. #define SCANCODE_N              49
  91. #define SCANCODE_M              50
  92.  
  93. #define SCANCODE_ESCAPE         1
  94. #define SCANCODE_ENTER          28
  95. #define SCANCODE_RIGHTCONTROL   97
  96. #define SCANCODE_CONTROL        97
  97. #define SCANCODE_RIGHTALT       100
  98. #define SCANCODE_LEFTCONTROL    29
  99. #define SCANCODE_LEFTALT        56
  100. #define SCANCODE_SPACE          57
  101.  
  102. #define SCANCODE_F1             59
  103. #define SCANCODE_F2             60
  104. #define SCANCODE_F3             61
  105. #define SCANCODE_F4             62
  106. #define SCANCODE_F5             63
  107. #define SCANCODE_F6             64
  108. #define SCANCODE_F7             65
  109. #define SCANCODE_F8             66
  110. #define SCANCODE_F9             67
  111. #define SCANCODE_F10            68
  112.  
  113. #define KEY_EVENTRELEASE 0
  114. #define KEY_EVENTPRESS 1
  115.  
  116. #define SCANCODE_0 11
  117. #define SCANCODE_1 2
  118. #define SCANCODE_2 3
  119. #define SCANCODE_3 4
  120. #define SCANCODE_4 5
  121. #define SCANCODE_5 6
  122. #define SCANCODE_6 7
  123. #define SCANCODE_7 8
  124. #define SCANCODE_8 9
  125. #define SCANCODE_9 10
  126.  
  127. #define SCANCODE_LEFTSHIFT 42
  128. #define SCANCODE_RIGHTSHIFT 54
  129. #define SCANCODE_TAB 15
  130.  
  131. #define SCANCODE_F11 87
  132. #define SCANCODE_F12 88
  133. #define SCANCODE_NEXT 81
  134. #define SCANCODE_PRIOR 73
  135. #define SCANCODE_BS 14
  136. /*
  137. #define SCANCODE_asciicircum 1
  138. */
  139. #define SCANCODE_bracketleft 26
  140. #define SCANCODE_bracketright 27
  141. #define SCANCODE_comma 51
  142. #define SCANCODE_period 52
  143. #define SCANCODE_slash 53
  144. #define SCANCODE_semicolon 39
  145. #define SCANCODE_grave 40
  146. #define SCANCODE_minus 12
  147. #define SCANCODE_equal 13
  148. #define SCANCODE_numbersign 41
  149. #define SCANCODE_ltgt 43
  150. #define SCANCODE_scrolllock 70
  151.  
  152. void (*DrawPixel)(int, xcolnr);
  153.  
  154. static char pixel_buffer[3200];
  155. char *xlinebuffer;
  156.  
  157. long int xcolors[4096];
  158.  
  159. static int next_pos;
  160. static bool next_double;
  161.  
  162. void prepare_line(int y, bool need_double)
  163. {
  164.     next_pos = y;
  165.     next_double = need_double;
  166.     xlinebuffer = pixel_buffer;
  167. }
  168.  
  169. void flush_line(void)
  170. {
  171.     asm ("
  172.          cld
  173.          movl $_pixel_buffer, %esi
  174.          movl _next_pos, %ebx
  175.          cmpb $0, _use_dos_hicolor
  176.          je DRAWIC
  177.          movl $1600, %eax
  178.          mull %ebx
  179.          addl $0xd0000000, %eax
  180.          movl %eax, %edi
  181.          movl $400, %ecx
  182.          rep
  183.          movsl
  184.          cmpb $0, _next_double
  185.          je END
  186.          subl $1600, %esi
  187.          movl $400, %ecx
  188.          rep
  189.          movsl
  190.          jmp END
  191.      DRAWIC:
  192.          movl $800, %eax
  193.          mull %ebx
  194.          addl $0xd0000000, %eax
  195.          movl %eax, %edi
  196.          movl $200, %ecx
  197.          rep
  198.          movsl
  199.          cmpb $0, _next_double
  200.          je END
  201.          subl $800, %esi
  202.          movl $200, %ecx
  203.          rep
  204.          movsl
  205.      END:
  206.     ");
  207. }
  208.  
  209. static void DrawPixel8(int x, xcolnr col)
  210. {
  211.     *(char *)xlinebuffer = col;
  212.     xlinebuffer += 1;
  213. }
  214.  
  215. static void DrawPixel16(int x, xcolnr col)
  216. {
  217.     *(short *)xlinebuffer = col;
  218.     xlinebuffer += 2;
  219. }
  220.  
  221. void flush_screen(void)
  222. {
  223. }
  224.  
  225. static __inline__ unsigned long doMask(int p, int bits, int shift)
  226. {
  227.     /* p is a value from 0 to 15 (Amiga color value)
  228.      * scale to 0..255, shift to align msb with mask, and apply mask */
  229.  
  230.     unsigned long val = p * 0x11111111UL;
  231.     val >>= (32 - bits);
  232.     val <<= shift;
  233.  
  234.     return val;
  235. }
  236.  
  237. static void init_colors(void)
  238. {
  239.     if (use_dos_hicolor) {
  240.        int i;
  241.        for(i=0; i<4096; i++) {
  242.        int r = i >> 8;
  243.        int g = (i >> 4) & 0xF;
  244.        int b = i & 0xF;
  245.        xcolors[i] = (doMask(r, R_WEIGHT, G_WEIGHT + B_WEIGHT)
  246.              | doMask(g, G_WEIGHT, B_WEIGHT)
  247.              | doMask(b, B_WEIGHT, 0));
  248.        }
  249.     } else {
  250.        /* This is kind of kludgy...
  251.     * Try to allocate as many different colors as possible. */
  252.        int step = 16, count = 0, col;
  253.        int allocated[4096];
  254.        memset(allocated,0,sizeof allocated);
  255.  
  256.        while ((step/=2) > 0) {
  257.        int r, g, b;
  258.        for(r = 0; r < 16; r += step) {
  259.            for(g = 0; g < 16; g += step) {
  260.            for(b = 0; b < 16; b += step) {
  261.                int cnr = (r << 8) + (g << 4) + b;
  262.                if (++count == 256)
  263.                goto finished;
  264.                if (!allocated[cnr]) {
  265.                allocated[cnr] = true;
  266.                xcolors[cnr] = count-1;
  267.                GrSetColor(count-1, (r*255+7)/15, (g*255+7)/15, (b*255+7)/15);
  268.                }
  269.            }
  270.            }
  271.        }
  272.        }
  273.        finished:
  274.        for(col = 0; col < 4096; col++) {
  275.        int cnr = col;
  276.        if (!allocated[cnr]) {
  277.            int r = cnr >> 8;
  278.            int g = (cnr >> 4) & 0xF;
  279.            int b = cnr & 0xF;
  280.            int maxd = 4096,best = 0;
  281.            int c2;
  282.            for(c2 = 0; c2 < 4096; c2++)
  283.            if (allocated[c2]) {
  284.                int r2 = c2 >> 8;
  285.                int g2 = (c2 >> 4) & 0xF;
  286.                int b2 = c2 & 0xF;
  287.                int dist = abs(r2-r)*2 + abs(g2-g)*3 + abs(b2-b);
  288.                if (dist < maxd) {
  289.                maxd = dist;
  290.                best = c2;
  291.                }
  292.            }
  293.            cnr = best;
  294.        }
  295.        xcolors[col] = xcolors[cnr];
  296.        }
  297.     }
  298. }
  299.  
  300. bool buttonstate[3] = { false, false, false };
  301. int lastmx, lastmy;
  302. bool newmousecounters = false;
  303.  
  304. static bool keystate[256];
  305.  
  306. static int scancode2amiga(int scancode)
  307. {
  308.     switch(scancode) {
  309.      case SCANCODE_A: return AK_A;
  310.      case SCANCODE_B: return AK_B;
  311.      case SCANCODE_C: return AK_C;
  312.      case SCANCODE_D: return AK_D;
  313.      case SCANCODE_E: return AK_E;
  314.      case SCANCODE_F: return AK_F;
  315.      case SCANCODE_G: return AK_G;
  316.      case SCANCODE_H: return AK_H;
  317.      case SCANCODE_I: return AK_I;
  318.      case SCANCODE_J: return AK_J;
  319.      case SCANCODE_K: return AK_K;
  320.      case SCANCODE_L: return AK_L;
  321.      case SCANCODE_M: return AK_M;
  322.      case SCANCODE_N: return AK_N;
  323.      case SCANCODE_O: return AK_O;
  324.      case SCANCODE_P: return AK_P;
  325.      case SCANCODE_Q: return AK_Q;
  326.      case SCANCODE_R: return AK_R;
  327.      case SCANCODE_S: return AK_S;
  328.      case SCANCODE_T: return AK_T;
  329.      case SCANCODE_U: return AK_U;
  330.      case SCANCODE_V: return AK_V;
  331.      case SCANCODE_W: return AK_W;
  332.      case SCANCODE_X: return AK_X;
  333.      case SCANCODE_Y: return AK_Y;
  334.      case SCANCODE_Z: return AK_Z;
  335.  
  336.      case SCANCODE_0: return AK_0;
  337.      case SCANCODE_1: return AK_1;
  338.      case SCANCODE_2: return AK_2;
  339.      case SCANCODE_3: return AK_3;
  340.      case SCANCODE_4: return AK_4;
  341.      case SCANCODE_5: return AK_5;
  342.      case SCANCODE_6: return AK_6;
  343.      case SCANCODE_7: return AK_7;
  344.      case SCANCODE_8: return AK_8;
  345.      case SCANCODE_9: return AK_9;
  346.  
  347.      case SCANCODE_KEYPAD0: return AK_NP0;
  348.      case SCANCODE_KEYPAD1: return AK_NP1;
  349.      case SCANCODE_KEYPAD2: return AK_NP2;
  350.      case SCANCODE_KEYPAD3: return AK_NP3;
  351.      case SCANCODE_KEYPAD4: return AK_NP4;
  352.      case SCANCODE_KEYPAD5: return AK_NP5;
  353.      case SCANCODE_KEYPAD6: return AK_NP6;
  354.      case SCANCODE_KEYPAD7: return AK_NP7;
  355.      case SCANCODE_KEYPAD8: return AK_NP8;
  356.      case SCANCODE_KEYPAD9: return AK_NP9;
  357.  
  358.      case SCANCODE_F1: return AK_F1;
  359.      case SCANCODE_F2: return AK_F2;
  360.      case SCANCODE_F3: return AK_F3;
  361.      case SCANCODE_F4: return AK_F4;
  362.      case SCANCODE_F5: return AK_F5;
  363.      case SCANCODE_F6: return AK_F6;
  364.      case SCANCODE_F7: return AK_F7;
  365.      case SCANCODE_F8: return AK_F8;
  366.      case SCANCODE_F9: return AK_F9;
  367.      case SCANCODE_F10: return AK_F10;
  368.  
  369.      case SCANCODE_BS: return AK_BS;
  370.      case SCANCODE_CONTROL: return AK_CTRL;
  371.      case SCANCODE_TAB: return AK_TAB;
  372.      case SCANCODE_LEFTALT: return AK_LALT;
  373.      case SCANCODE_RIGHTALT: return AK_RALT;
  374.      case SCANCODE_ENTER: return AK_RET;
  375.      case SCANCODE_SPACE: return AK_SPC;
  376.      case SCANCODE_LEFTSHIFT: return AK_LSH;
  377.      case SCANCODE_RIGHTSHIFT: return AK_RSH;
  378.      case SCANCODE_ESCAPE: return AK_ESC;
  379.  
  380.      case SCANCODE_CURSORBLOCKUP: return AK_UP;
  381.      case SCANCODE_CURSORBLOCKDOWN: return AK_DN;
  382.      case SCANCODE_CURSORBLOCKLEFT: return AK_LF;
  383.      case SCANCODE_CURSORBLOCKRIGHT: return AK_RT;
  384.  
  385.      case SCANCODE_F11: return AK_BACKSLASH;
  386. /*
  387.      case SCANCODE_asciicircum: return AK_00;
  388.  */
  389.      case SCANCODE_bracketleft: return AK_LBRACKET;
  390.      case SCANCODE_bracketright: return AK_RBRACKET;
  391.      case SCANCODE_comma: return AK_COMMA;
  392.      case SCANCODE_period: return AK_PERIOD;
  393.      case SCANCODE_slash: return AK_SLASH;
  394.      case SCANCODE_semicolon: return AK_SEMICOLON;
  395.      case SCANCODE_grave: return AK_QUOTE;
  396.      case SCANCODE_minus: return AK_MINUS;
  397.      case SCANCODE_equal: return AK_EQUAL;
  398.  
  399.     /* This one turns off screen updates. */
  400.      case SCANCODE_scrolllock: return AK_inhibit;
  401.  
  402. #if 0 /* No unique scancode for these yet. I need a Win95 keyboard :-( */
  403.      case SCANCODE_NEXT: return AK_RAMI;          /* PgUp mapped to right amiga */
  404.      case SCANCODE_PRIOR: return AK_LAMI;         /* PgDn mapped to left amiga */
  405. #endif
  406.  
  407. /*#ifdef KBD_LANG_DE*/
  408.      case SCANCODE_numbersign: return AK_NUMBERSIGN;
  409.      case SCANCODE_ltgt: return AK_LTGT;
  410. /*#endif*/
  411.     }
  412.     return -1;
  413. }
  414.  
  415. static void my_kbd_handler(void)
  416. {
  417.     int scancode, newstate, akey;
  418.  
  419.     scancode = inportb(0x60);
  420.     newstate = !(scancode & 0x80);
  421.     scancode = scancode & 0x7f;
  422.     outportb(0x20, 0x20);
  423.  
  424.     akey = scancode2amiga(scancode);
  425.     if (scancode == SCANCODE_F12)
  426.     specialflags |= SPCFLAG_BRK;
  427.     if (keystate[scancode] == newstate)
  428.     return;
  429.     keystate[scancode] = newstate;
  430.  
  431.     if (akey == -1)
  432.     return;
  433.  
  434.     if (newstate == KEY_EVENTPRESS) {
  435.     if (akey == AK_inhibit)
  436.         inhibit_frame ^= 1;
  437.     else
  438.         record_key (akey << 1);
  439.     } else
  440.     record_key ((akey << 1) | 1);
  441.  
  442.     /* "Affengriff" */
  443.     if(keystate[AK_CTRL] && keystate[AK_LAMI] && keystate[AK_RAMI])
  444.     MC68000_reset();
  445. }
  446.  
  447. _go32_dpmi_seginfo old_kbd_handler, new_kbd_handler;
  448.  
  449. int graphics_init(void)
  450. {
  451.     int i, res;
  452.     _go32_dpmi_registers regs;
  453.  
  454.     _go32_dpmi_get_protected_mode_interrupt_vector(9, &old_kbd_handler);
  455.     new_kbd_handler.pm_offset = (int)my_kbd_handler;
  456.     new_kbd_handler.pm_selector = _go32_my_cs();
  457.     res = _go32_dpmi_allocate_iret_wrapper(&new_kbd_handler);
  458.     if(res!=0) {
  459.     fprintf (stderr, "Error: Can't allocate iret_wrapper");
  460.     return 0;
  461.     }
  462.     res = _go32_dpmi_set_protected_mode_interrupt_vector(9, &new_kbd_handler);
  463.     if(res!=0) {
  464.     fprintf (stderr, "Error: Can't set protected mode interrupt vector");
  465.     return 0;
  466.     }
  467.     regs.x.ax=0;
  468.     regs.x.ss=regs.x.sp=regs.x.flags=0;
  469.     _go32_dpmi_simulate_int(0x33, ®s);
  470.     if(regs.x.ax==0) {
  471.     fprintf (stderr, "Error: Mouse driver not present");
  472.     return 0;
  473.     }
  474.     if(use_dos_hicolor) {
  475.     GrSetMode(GR_width_height_color_graphics, 800, 600, 32768);
  476.     DrawPixel = DrawPixel16;
  477.     } else {
  478.     GrSetMode(GR_width_height_color_graphics, 800, 600, 256);
  479.     DrawPixel = DrawPixel8;
  480.     }
  481.  
  482.     init_colors();
  483.  
  484.     buttonstate[0] = buttonstate[1] = buttonstate[2] = false;
  485.     for(i = 0; i < 256; i++)
  486.     keystate[i] = false;
  487.  
  488.     lastmx = lastmy = 0; newmousecounters = false;
  489.     return 1;
  490. }
  491.  
  492. void graphics_leave(void)
  493. {
  494.     GrSetMode(GR_default_text);
  495.     _go32_dpmi_set_protected_mode_interrupt_vector(9, &old_kbd_handler);
  496. }
  497.  
  498. void handle_events(void)
  499. {
  500.     _go32_dpmi_registers regs;
  501.  
  502.     regs.x.ax=11;
  503.     regs.x.ss=regs.x.sp=regs.x.flags=0;
  504.     _go32_dpmi_simulate_int(0x33, ®s);
  505.     lastmx += (short)regs.x.cx;
  506.     lastmy += (short)regs.x.dx;
  507.     regs.x.ax=3;
  508.     regs.x.ss=regs.x.sp=regs.x.flags=0;
  509.     _go32_dpmi_simulate_int(0x33, ®s);
  510.     buttonstate[0] = regs.x.bx & 1;
  511.     buttonstate[1] = regs.x.bx & 4;
  512.     buttonstate[2] = regs.x.bx & 2;
  513. }
  514.  
  515. bool debuggable(void)
  516. {
  517.     return false;
  518. }
  519.  
  520. bool needmousehack(void)
  521. {
  522.     return false;
  523. }
  524.  
  525. void LED(int on)
  526. {
  527. }
  528.